package com.lw.sbdemo2.common.utils;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;

@Slf4j
public class LwUtil {

    // 这个类不能实例化
    private LwUtil() {

    }

    public static void main(String[] args) {
        log.error("error message");
        System.out.println(div("1.55", "1.554", 6));
    }

    /**
     * 获取用户真实IP地址，不使用request.getRemoteAddr()的原因是有可能用户使用了代理软件方式避免真实IP地址,
     * 可是，如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP值
     *
     * @return ip
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        System.out.println("x-forwarded-for ip: " + ip);
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值，第一个ip才是真实ip
            if (ip.indexOf(",") != -1) {
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
            System.out.println("Proxy-Client-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
            System.out.println("WL-Proxy-Client-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
            System.out.println("HTTP_CLIENT_IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            System.out.println("HTTP_X_FORWARDED_FOR ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
            System.out.println("X-Real-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            System.out.println("getRemoteAddr ip: " + ip);
        }
        System.out.println("获取客户端ip: " + ip);
        return ip;
    }

    /************************   数值相关处理   ************************/

    /**
     * 两个字符串比较
     *
     * @param v1
     * @param v2
     * @return
     * @author LinWang
     * @createTime 2015-4-26
     */
    public static int compareTo(String v1, String v2) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.compareTo(b2);
    }

    /**
     * 两个字符串相加（提供精确的加法运算）
     *
     * @param v1 被加数
     * @param v2 加数
     * @return
     * @author linwang
     * @createTime 2015-3-30
     */
    public static String add(String v1, String v2) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.add(b2).toString();
    }

    /**
     * 两个字符串相减（提供精确的减法运算）
     *
     * @param v1 被减数
     * @param v2 减数
     * @return
     * @author linwang
     * @createTime 2015-3-30
     */
    public static String sub(String v1, String v2) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.subtract(b2).toString();
    }

    /**
     * 两个字符串相乘（提供精确的乘法运算）
     *
     * @param v1 被乘数
     * @param v2 乘数
     * @return
     * @author linwang
     * @createTime 2015-3-30
     */
    public static String mul(String v1, String v2) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.multiply(b2).toString();
    }

    /**
     * 提供（相对）精确的除法运算
     * 当发生除不尽的情况时，由scale参数指定精度，以后的数字四舍五入
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 表示表示需要精确到小数点以后几位
     * @return
     * @author linwang
     * @createTime 2015-3-30
     */
    public static String div(String v1, String v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The   scale   must   be   a   positive   integer   or   zero");
        }
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);

        //ROUND_HALF_UP: 遇到.5的情况时往上近似,例: 1.5 ->;2
        //ROUND_HALF_DOWN : 遇到.5的情况时往下近似,例: 1.5 ->;1
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 提供精确的小数位四舍五入处理
     *
     * @param v     需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return
     * @author linwang
     * @createTime 2015-3-30
     */
    public static String roundBig(String v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The   scale   must   be   a   positive   integer   or   zero");
        }
        BigDecimal b = new BigDecimal(v);
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).toString();
    }


    /************************   字符串相关处理   ************************/

    /**
     * 判断字符串是否是数字
     *
     * @param str
     * @return
     * @author linwang
     * @createTime 2013-12-26
     */
    public static boolean isNum(String str) {
        return str.matches("^[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$");
    }

    /**
     * Integer.parseInt加上非空判断-为null的设置为0
     *
     * @param str 需要转换成整数的字符串
     * @return
     */
    public static int toInt(String str) {
        Integer integer = toInteger(str);
        return (integer == null ? 0 : integer.intValue());
    }

    /**
     * toInt的后续方法
     *
     * @param str
     * @return
     */
    public static Integer toInteger(String str) {
        if (str == null) {
            return null;
        }
        try {
            return new Integer(str.trim());
        } catch (NumberFormatException nfe) {
            return null;
        }
    }

    /**
     * 字符串+1方法，该方法将其结尾的整数+1,适用于任何以整数结尾的字符串,不限格式，不限分隔符。
     *
     * @param testStr 要+1的字符串
     * @return +1后的字符串
     * @throws NumberFormatException
     * @author linwang
     */
    public static String addOne(String testStr) {
        String[] strs = testStr.split("[^0-9]");//根据不是数字的字符拆分字符串
        String numStr = strs[strs.length - 1];//取出最后一组数字
        if (numStr != null && numStr.length() > 0) {//如果最后一组没有数字(也就是不以数字结尾)，抛NumberFormatException异常
            int n = numStr.length();//取出字符串的长度
            int num = Integer.parseInt(numStr) + 1;//将该数字加一
            String added = String.valueOf(num);
            n = Math.min(n, added.length());
            //拼接字符串
            return testStr.subSequence(0, testStr.length() - n) + added;
        } else {
            throw new NumberFormatException();
        }
    }

    /**
     * 字符串前面补0
     *
     * @param str 想要补0的字符串
     * @param len 想要补0补到哪一位
     * @return
     */
    public static String padZeroLeft(String str, int len) {
        return padCharLeft(str, len, '0');
    }

    /**
     * 字符串前面补某字符-对应还有padCharRight右边补充方法
     *
     * @param str     想要补某字符的字符串
     * @param len     想要补某字符补到哪一位
     * @param padChar 表示你想要补充什么字符
     * @return
     */
    public static String padCharLeft(String str, int len, char padChar) {
        if (str == null || str.length() == 0) {
            return str;
        }
        if (str.length() >= len) {
            return str;
        }
        StringBuffer sb = new StringBuffer(str);
        int max = len - str.length();
        for (int i = 0; i < max; i++) {
            sb.insert(0, padChar);
        }
        return sb.toString();
    }

    /**
     * 去除下划线并修改紧随字母为大写
     *
     * @param underline 对象字符串
     * @return
     */
    public static String removeUnderline(String underline) {
        StringBuffer sb = new StringBuffer(underline);
        int count = sb.indexOf("_");
        while (count != 0) {
            int num = sb.indexOf("_", count);
            count = num + 1;
            if (num != -1) {
                char ss = sb.charAt(count);
                char ia = (char) (ss - 32);
                //String ia = StringUtils.upperCase(ss+""); 使用此方法也可
                sb.replace(count, count + 1, ia + "");
                System.out.println(sb.toString());
            }
        }
        String ss = sb.toString().replaceAll("_", "");
        System.out.println(ss + "转换完成");
        return "";
    }

    /************************   集合相关处理   ************************/

    /**
     * 利用HashSet移除List重复元素并排序
     *
     * @param list
     * @return
     * @author linwang
     * @createTime 2014-1-8
     */
    public static List<String> removeDuplicateAndSort(List<String> list) {
        HashSet<String> hashSet = new HashSet<String>(list);
        list.clear();
        list.addAll(hashSet);
        Collections.sort(list, new Comparator<String>() {
            public int compare(String arg0, String arg1) {
                return arg0.compareTo(arg1);
            }
        });
        return list;
    }
}
